#include <iostream>
#include <stdio.h>
#include <complex>
#include <thread>
#include <complex>
#include <cstring>
#include <mutex>
#include "process_data.hpp"
#include "read_signal.hpp"
#include "qpsk_mod.hpp"
#include "myfft.hpp"
#include "SSB.hpp"
#include "DMRS.hpp"
#include "main.hpp"
#include "my_usrp.hpp"

// complex<double> *p_data;
std::complex<double> pbch[576];
int head_buf = 0;
int tail_buf = 0;
int slot_in_buff = 0;
bool stop_flag = false;
// short *pre_buff = new short[SAMPLE_PER_BUFF * 2 * 100];

MY_PROCESS_DATA::MY_PROCESS_DATA(int NID, std::size_t size, bool flag) : size(size), fft(size, flag)
{
    PBCH_DMRS(pbch_dmrs);
    PDSCH_DMRS(pdsch_dmrs);
    int p[127];
    int s[127];
    PSS(NID, p);
    SSS(NID, s);
    for (int i = 0; i < 127; i++)
    {
        pss[i].real(p[i]);
        pss[i].imag(0);
        sss[i].real(s[i]);
        sss[i].imag(0);
    }
}
void MY_PROCESS_DATA::process_data()
{
    myfft fft(512, false);

    auto read_result = read_file("./test.txt");
    size_t size = FFT_SIZE;
    if (read_result.first == nullptr)
    {
        std::cout << "empty file!";
        return;
    }
    std::cout << "read_result.second: " << read_result.second << std::endl;
    for (uint64_t i = 0; i < read_result.second; i += SYMBOLS_ONE_FRAME * 2)
    {

        static auto time_stamp = std::chrono::high_resolution_clock::now();

        std::complex<double> *data_queue = modulation(read_result.first + i, SYMBOLS_ONE_FRAME);
        std::complex<double> *p_data = new std::complex<double>[SPACE];
        add_ssb_dmrs(data_queue, p_data);
        for (uint16_t j = 0; j < SLOT_NUM; j++)
        {
            for (uint16_t k = 0; k < SYMBOL_NUM; k++)
            {
                fft.exec_fft(p_data + j * 333, size);
                short *pre_date_time = fft.get_result();
                while (head_buf - tail_buf == -1)
                {
                    std::cout << "buff full, waiting" << std::endl;
                }
                mtx.lock();
                if (k == 0)
                {
                    std::memcpy(buff + head_buf * SAMPLE_PER_BUFF * 2,
                                pre_date_time + (FFT_SIZE - N_CP_FIRST) * 2,
                                2 * N_CP_FIRST * sizeof(short));
                    std::memcpy(buff + head_buf * SAMPLE_PER_BUFF * 2 + N_CP_FIRST * 2,
                                pre_date_time,
                                2 * FFT_SIZE * sizeof(short));
                }
                else
                {
                    std::memcpy(buff + head_buf * SAMPLE_PER_BUFF * 2 + k * FFT_SIZE * 2 + N_CP_FIRST * 2 + N_CP * (k - 1) * 2,
                                pre_date_time + (FFT_SIZE - N_CP) * 2,
                                2 * N_CP * sizeof(short));
                    std::memcpy(buff + head_buf * SAMPLE_PER_BUFF * 2 + k * FFT_SIZE * 2 + N_CP_FIRST * 2 + N_CP * k * 2,
                                pre_date_time,
                                2 * FFT_SIZE * sizeof(short));
                    if (k == SYMBOL_NUM - 1)
                    {
                        head_buf++;
                        head_buf %= BUFF_SIZE;
                    }
                }
                mtx.unlock();
                delete[] pre_date_time;
            }
        }
        delete[] p_data;
        delete[] data_queue;

        auto time_temp = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(time_temp - time_stamp).count();
        std::cout << "process data cost time: " << duration << std::endl;
        time_stamp = time_temp;
    }
    std::cout << "all data processed!" << std::endl;
    stop_flag = true;
}
MY_PROCESS_DATA::~MY_PROCESS_DATA()
{
}
// void MY_PROCESS_DATA::runThread()
// {
//     std::thread thread_;
//     thread_ = std::thread(&MY_PROCESS_DATA::process_data);
//     if (thread_.joinable())
//     {
//         thread_.join();
//     }
// }

void MY_PROCESS_DATA::add_ssb_dmrs(std::complex<double> *data, std::complex<double> *p_data)
{
    int i = 0; // ʱ϶����
    int j = 0; // ���ż���
    int k = 0; // ���ݼ���

    memcpy(p_data + 17, data, 300 * sizeof(std::complex<double>)); // ��һ��ʱ϶��0���������ݣ�ǰ����17�����ز���������������16������ʹ��300��
    k = k + 300;
    for (int m = 0; m < 150; m++) // ��1�����Űڷ�pbschdmrs
    {
        p_data[333 + 17 + 2 * m] = data[k + m];
        p_data[333 + 17 + 2 * m + 1] = pdsch_dmrs[m];
        // std::cout<<m<<std::endl;
    }
    k = k + 150;

    for (int m = 0; m < 144; m++)
    {
        pbch[4 * m] = pbch_dmrs[m];
    }

    // ��2/3/4/5�ĸ����Űڷ�SSB
    // �ڶ�������
    memcpy(p_data + 17 + 2 * 333, data + k, 30 * sizeof(std::complex<double>));
    k = k + 30;
    memcpy(p_data + 17 + 2 * 333 + 78, pss, 127 * sizeof(std::complex<double>));
    memcpy(p_data + 17 + 2 * 333 + 270, data + k, 30 * sizeof(std::complex<double>));
    k = k + 30;

    // ����������
    memcpy(p_data + 17 + 3 * 333, data + k, 30 * sizeof(std::complex<double>));
    k = k + 30;
    memcpy(p_data + 17 + 3 * 333 + 30, pbch, 240 * sizeof(std::complex<double>));
    memcpy(p_data + 17 + 3 * 333 + 270, data + k, 30 * sizeof(std::complex<double>));
    k = k + 30;

    // ���ĸ�����
    memcpy(p_data + 17 + 4 * 333, data + k, 30 * sizeof(std::complex<double>));
    k = k + 30;
    memcpy(p_data + 17 + 4 * 333 + 30, pbch + 240, 48 * sizeof(std::complex<double>));
    memcpy(p_data + 17 + 4 * 333 + 78, sss, 127 * sizeof(std::complex<double>));
    memcpy(p_data + 17 + 4 * 333 + 30 + 16 * 12, pbch + 288, 48 * sizeof(std::complex<double>));
    memcpy(p_data + 17 + 4 * 333 + 270, data + k, 30 * sizeof(std::complex<double>));
    k = k + 30;

    // ���������?
    memcpy(p_data + 17 + 5 * 333, data + k, 30 * sizeof(std::complex<double>));
    k = k + 30;
    memcpy(p_data + 17 + 5 * 333 + 30, pbch + 336, 240 * sizeof(std::complex<double>));
    memcpy(p_data + 17 + 5 * 333 + 270, data + k, 30 * sizeof(std::complex<double>));
    k = k + 30;

    j = 6;

    // ֮��ѭ����������
    for (i = 0; i < 20; i++)
    {
        for (int j = 0; j < 14; j++)
        {
            if (j == 1)
            {
                for (int m = 0; m < 150; m++) // ��1�����Űڷ�pbschdmrs
                {
                    p_data[(j + i * 14) * 333 + 17 + 2 * m] = data[k + m];
                    p_data[(j + i * 14) * 333 + 17 + 2 * m + 1] = pdsch_dmrs[m];
                }
                k = k + 150;
            }
            else
            {
                memcpy(p_data + 17 + (j + i * 14) * 333, data + k, 300 * sizeof(std::complex<double>));
                k = k + 300;
            }
        }
        j = 0;
    }
    // printf("k:,%d", k);
}
